package com.tweetgraph.util;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import twitter4j.Query;
import twitter4j.QueryResult;
import twitter4j.Tweet;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

public class TwitterSearchUtil {

	private static Logger logger = Logger.getLogger(TwitterSearchUtil.class.getName());
	private static final long numSecondsToRun = 40;
	private static final long gapBetweenRuns = 10;
	
	
	/**
	 * 
	 * @param hashTag
	 */
	public static void processTwitterQuery(String hashTag){
		
		/*
		 * 1. Look for the query object from the database with the above hashtag
		 * 2. if no query obj exists -> return 
		 * 3. if query object exists, Run the search query with intermittent saves of the 
		 * twitter objects. 
		 */
		
		Key key = KeyFactory.createKey("QueryResult", hashTag);
		
		/*
		 * Check if there is an entity with the same #hashtag in the db
		 */
		DatastoreService datastore =  DatastoreServiceFactory.getDatastoreService();
		Entity existEnt = null;
		
		try{
			existEnt = datastore.get(key);
		}catch(EntityNotFoundException e){
			//do nothing 
		}

		if(existEnt == null){
			return;
		}
		
		/*
		 * Run the twitter query -> keep delay between each run (10 seconds right now)
		 * inside the runTwitterQuery method. Run this method until the timegap 
		 * is greater than 4 mins.
		 * and update the page results for each iteration.
		 */
		long start = System.currentTimeMillis();
		long end = System.currentTimeMillis();
		
		Entity ent = getRunDurationsFromDB();
		long runDuration = (Long)ent.getProperty("maxRunDuration");
		long delay = (Long)ent.getProperty("delayBetweenRuns");
		
		while((end-start)/1000 < runDuration){
			runTwitterQuery(hashTag,delay);
			end = System.currentTimeMillis();
		}
		
	}

	
	/**
	 * 
	 * @return
	 */
	private static Entity getRunDurationsFromDB(){
		Key key = KeyFactory.createKey("Config","RunDurationConfig");
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		
		Entity ent = null;
		
		try{
			ent = datastore.get(key);
		}catch(EntityNotFoundException e){
		}
		
		if(ent == null){
			//insert a new entity with times
			ent = new Entity(key);
			ent.setUnindexedProperty("maxRunDuration", numSecondsToRun);
			ent.setUnindexedProperty("delayBetweenRuns",gapBetweenRuns );
			datastore.put(ent);
		}
		
		return ent;
		
		
	}
	
	/**
	 * 
	 * @param hashTag
	 */
	private static void runTwitterQuery(String searchTerm, long delay){
		Twitter twitter = new TwitterFactory().getInstance();
		int page = 1;

		try{
			Query query = new Query(searchTerm);
			query.setPage(1);
			query.setRpp(500);
			QueryResult result = twitter.search(query);
			logger.info("Number of results per page:" + result.getResultsPerPage() + ", page no.:" + result.getPage());
			
			
			List<Tweet> list = result.getTweets();
			
			while(list != null && list.size() > 0){
				/*
				 * save this list of tweets to DB and get the next page
				 */
				logger.info("The results from twitter:" + list.toString());
				saveTweetsToDB(list, searchTerm);
				query.setPage(++page);
				
				/*
				 * Set a delay for 10 seconds -- the over all duration cannot exceed 10 mins.
				 */
				try{
					Thread.sleep(delay * 1000);
				}catch(Exception e){
					//do nothing
				}
				
				result = twitter.search(query);
				list = result.getTweets();
				
			}		
		}catch(Exception e){
			e.printStackTrace();
		}
		
	}
	
	
	/**
	 * 
	 * @param list
	 * @param hashTag
	 */
	private static void saveTweetsToDB(List<Tweet> list, String hashTag){

		Key key = KeyFactory.createKey("QueryResult", hashTag);
		DatastoreService datastore =  DatastoreServiceFactory.getDatastoreService();
		Key childK = null;
		Entity ent1 = null;
		List<Entity> entityList = new ArrayList<Entity>();
		
		for(Tweet tweet:list){
			childK = KeyFactory.createKey(key, "tweet",""+tweet.getId());
			ent1 = new Entity(childK);
			ent1.setUnindexedProperty("type", "tweet");
			ent1.setProperty("text",tweet.getText());
			ent1.setUnindexedProperty("fromUser", tweet.getFromUser());
			ent1.setUnindexedProperty("toUser", tweet.getToUser());
			ent1.setUnindexedProperty("id", tweet.getId());
			ent1.setUnindexedProperty("createdDate", tweet.getCreatedAt());
			ent1.setUnindexedProperty("location", tweet.getLocation());

			entityList.add(ent1);
		}
		datastore.put(entityList);
		
	}
	
}
